package com.kaixinff.kaixin001.xw;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.TimeZone;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.json.JSONException;
import org.json.JSONObject;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.kaixinff.kaixin001.util.KXClient;
import com.kaixinff.kaixin001.util.KXUtil;
import com.kaixinff.net.NameValuePair;

public class Task implements Runnable{
	
	private static final String HOST_URL = KXUtil.HOST_URL + "/!spiderman";
	private static final String INDEX_URL = HOST_URL + "/index.php";
	private static final String JOB_URL = HOST_URL + "/job.php";
	private static final String FIGHT_URL = HOST_URL + "/fight.php";
	public static final String COLLECTION_URL = HOST_URL + "/inventory.php?item=collection";
	private int cid = 2;
	private List<Integer> cids;
	private long energy;
	private int stamina;
	private int health;
	private int level;
	private long cash;
	private long neededEnergy;
	private KXClient client;
	private String email;
	private MainThread manager;
	private int index;
	private boolean[] flags;
	
	public Task(MainThread t, int index, boolean[] flags) {
		this.manager = t;
		this.index = index;
		this.flags = flags;
	}
	
	@Override
	public void run() {
		System.out.printf("Thread[%1$s] start!", index);
		System.out.println();
		while (true) {
			UserWrap userWrap = manager.getUser();
			if (userWrap == null) {
				return;
			}
			if (userWrap.getUser() == null) {
				long now = System.currentTimeMillis();
				try {
					if (userWrap.getTime() - now > 0) {
						System.out.printf("Thread[%1$s] wait %2$s milliseconds.", index, (userWrap.getTime() - now) );
						System.out.println();
						Thread.sleep(userWrap.getTime() - now);
					}
					continue;
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			} else {
				email = userWrap.getUser().getId();
				try {
					client = KXClient.getInstance(email);
					neededEnergy = -1;
					
					get(INDEX_URL, null);
					String html = get(INDEX_URL + "?cid=4&t=" + Math.random(), INDEX_URL);
					cids =  new ArrayList<Integer>();
					if (html.indexOf("<script language=javascript>window.location = '/!spiderman/forecast_sea.php';</script></div>") > -1) {
						cid = 2;
						cids.add(2);
					} else {
						cid = 4;
						cids.add(2);
						cids.add(4);
					}
					
					if (flags[0]) {
						waitAMoment();
						doJob();
					} else if (flags[1]) {
						waitAMoment();
						doJob2();
					}
					if (flags[2]) {
						waitAMoment();
						fight();
					}
					if (flags[3]) {
						waitAMoment();
						help();
					}
					if (flags[4]) {
						waitAMoment();
						exchange();
					}
					if (flags[5]) {
						waitAMoment();
						secretbag();
					}
					if (flags[6]) {
						waitAMoment();
						dianchi();
					}
					if (flags[7]) {
						waitAMoment();
						mangu();
					}
					if (flags[8]) {
						waitAMoment();
						propterty();
					}
					if (flags[9]) {
						waitAMoment();
						gift();
					}
					if (flags[10]) {
						waitAMoment();
						consume();
					}
					if (flags[11]) {
						waitAMoment();
						gaming();
					}
					if (neededEnergy > -1) {
						userWrap.setTime(System.currentTimeMillis() + 240000 * neededEnergy + 10000);
					} else {
						userWrap.setTime(System.currentTimeMillis() + 3600000);
					}
					manager.setUser(userWrap);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	private int getCid(String html) {
		int cid = 2;
		Pattern p = Pattern.compile("\"cid\"[:]\"(\\d+?)\"");
		Matcher m = p.matcher(html);
		if (m.find()) {
			cid = Integer.parseInt(m.group(1));
		}
		
		cids =  new ArrayList<Integer>();
		p = Pattern.compile("<li onclick=\"XW\\.cityTransform\\((\\d+?)\\);\">");
		m = p.matcher(html);
		while (m.find()) {
			cids.add(Integer.parseInt(m.group(1)));
		}
		if (cids.isEmpty()) {
			cids.add(2);
		}
		
		return cid;		
	}
	
	private List<Integer> getCids(String html) {
		Pattern p = Pattern.compile("<li onclick=\"XW\\.cityTransform\\((\\d+?)\\);\">");
		Matcher m = p.matcher(html);
		while (m.find()) {
			cids.add(Integer.parseInt(m.group(1)));
		}
		if (cids.isEmpty()) {
			cids.add(2);
		}
		return cids;		
	}
	
	public void changeCity(int cid) throws IOException {
		get(KXUtil.XW_URL + "/hospital.php?cid=" + cid + "&t=" + Math.random(), null);
	}
	
	
	public void setEmail(String email) throws IOException {
		client = KXClient.getInstance(email);
	}
	
	private void waitAMoment() {
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	private JobData jobData1 = null;
	private JobData jobData2 = null;
	
	public void doJob() throws IOException {
		boolean forced = true;
		jobData1 = null;
		jobData2 = null;
		String cont = get(JOB_URL, null);
		energy = getEnergy(cont);
		Pattern p = Pattern.compile("XW[.]getJobListByPhase[(](\\d+?)[)]\">(.+?)<");
		Matcher m = p.matcher(cont);
		List<Integer> jpidList = new ArrayList<Integer>();
		while (m.find()) {
			int jpid = Integer.parseInt(m.group(1));
			jpidList.add(jpid);
		}
		int currentJpid = 0;
		JobData jobData = null;
		while (true) {
			for (int i = 0, n = jpidList.size(); i < n; i++) {
				int jpid = jpidList.get(i);
				if (jpid < currentJpid) {
					continue;
				}
				currentJpid = jpid;
				String html = get(getJobURL(jpid), JOB_URL);
				waitAMoment();
				boolean result = findJob(cid, jpid, html);
				if (result) {
					jobData = jobData1 == null ? jobData2 : jobData1;
					break;
				}
			}
			if (jobData == null) {
				jobData = jobData2;
			}
			while (jobData != null && (forced || energy >= jobData.energy)) {
				if (energy < jobData.energy) {
					forced = false;
				}
				waitAMoment();
				String jobId = jobData.id;
				String url = HOST_URL + "/!ajax_dojob.php?c_jid=" + jobId + "&cid=" + cid + "&tmp=" + Math.random();
				cont = get(url, JOB_URL);
				p = Pattern.compile("\\\\u4f60\\\\u7684(.+?)\\\\u8fd8\\\\u4e0d\\\\u5230(\\d+?)\\\\u4e2a\\\\uff0c\\\\u4f60\\\\u73b0\\\\u5728\\\\u7684\\\\u6570\\\\u91cf\\\\u662f(\\d+?)");
				m = p.matcher(cont);
				if (m.find()) {
					err("缺少道具！");
					jobData = jobData2;
				} else {
					energy = getEnergy(cont);
					log("执行任务：" + jobData.name + "，剩余能量：" + energy);
					boolean result = findJob(cid, jobData.jpid, cont);
					if (result) {
						jobData = jobData1 == null ? jobData2 : jobData1;
					}
				}
			}
			if (jobData != null && energy < jobData.energy) {
				neededEnergy = jobData.energy - energy;
				break;
			}
		}
	}
	
	public void doJob2() throws IOException {
		get(JOB_URL, null);
		
		JobData jobData = new JobData();
		
		jobData.city = 2;
		jobData.jpid = 9;
		jobData.id = "120";
		jobData.energy = 30;
		jobData.name = "在XXX的协助下捣毁散布末日谣言哄抬物价的国际商团";
		
//		jobData.city = 2;
//		jobData.jpid = 4;
//		jobData.id = "1";
//		jobData.energy = 1;
//		jobData.name = "在XXX的协助下捣毁散布末日谣言哄抬物价的国际商团";
		
		String jobUrl = HOST_URL + "/!job.php?c_jpid=" + jobData.jpid + "&flag=phase&cid=" + cid + "&tmp=" + Math.random();
		String cont = get(jobUrl, JOB_URL);
		int beginIndex = cont.indexOf("job_need_div_" + jobData.id);
		if (beginIndex > -1) {
			int endIndex = cont.indexOf("job_need_div_" + jobData.id, beginIndex + 1);
			jobBuy(cont.substring(beginIndex, endIndex), jobData.jpid);
		}
		energy = getEnergy(cont);
		while (energy >= jobData.energy) {
			////////////////////////////////////////////////////////////////////////////
//			cont = client.doGet(KXUtil.XW_URL + "/profile.php", null).getContent();
//			Pattern p = Pattern.compile("/50mgun\\.gif\"><br>×(\\d+?)</td>");
//			Matcher m = p.matcher(cont);
//			int num = 0;
//			if (m.find()) {
//				num = Integer.parseInt((m.group(1)));
//			}
//			if (num >= 2) {
//				return;
//			}
			////////////////////////////////////////////////////////////////////////////
			
			waitAMoment();
			String url = HOST_URL + "/!ajax_dojob.php?c_jid=" + jobData.id + "&cid=" + cid + "&tmp=" + Math.random();
			cont = get(url, JOB_URL);
			int e = getEnergy(cont);
			if (e == energy) {
//				doJob();
				err(cont);
				return;
			}
			energy = e;
			log("执行任务：" + jobData.name + "，剩余能量：" + energy);
		}
		neededEnergy = jobData.energy - energy;
	}
	
	private String get(String url, String referer) throws IOException {
		String cont = client.doGet(url, referer).getContent();
		checkUpdate(cont);
		return cont;
	}
	
	private String post(String url, String referer, NameValuePair[] params) throws IOException {
		String cont = client.doPost(url, referer, params).getContent();
		checkUpdate(cont);
		return cont;
	}

	private String getJobURL(int jpid) {
		return HOST_URL + "/!job.php?c_jpid=" + jpid + "&flag=phase&cid=" + cid + "&tmp=" + Math.random();
	}

	private boolean checkUpdate(String html) throws IOException {
		if (html.indexOf("XW.check({\"uplevel\":1});") != -1 || html.indexOf("XW.check({\\\"uplevel\\\":1});") != -1) {
			String cont = get(HOST_URL + "/!ajax_uplevel.php?cid=" + cid + "&tmp=" + Math.random(), null);
			energy = getEnergy(cont);
			level ++;
			neededEnergy = 0;
			log("^_^ 恭喜你，升级啦!");
			return true;
		}
		return false;
	}
	
	private int getEnergy(String html) {
		Pattern p = Pattern.compile("XW[.]processTimer[(]XW[.]ajaxNum,\"energy\",[-|\\d]+?,(\\d+?),(\\d+?),(\\d+?),(\\d+?),");
		Matcher m = p.matcher(html);
		if (m.find()) {
			return Integer.parseInt(m.group(1));
		}
		return 0;
	}
	
	public int getUserProperty(String html, String name) {
		Pattern p = Pattern.compile("XW[.]processTimer[(]XW[.]ajaxNum,\"" + name + "\",[-|\\d]+?,(\\d+?),(\\d+?),(\\d+?),(\\d+?),");
		Matcher m = p.matcher(html);
		if (!m.find()) {
			return -1;
		}
		return Integer.parseInt(m.group(1));
	}
	
	private static int getLevel(String html) {
		Pattern p = Pattern.compile("<span id=\"user_level\">(\\d+?)</span>级");
		Matcher m = p.matcher(html);
		int level = 0;
		if (m.find()) {
			level = Integer.parseInt(m.group(1));
		}
		return level;
	}

	private boolean findJob(int city, int jpid, String cont) throws IOException {
		JobData jobData = null;
		Pattern p = Pattern.compile("<div class=\"l ml5\">完成(\\d+?)%</div>");
		Matcher m = p.matcher(cont);
		int index = 0;
		String jobString = null;
		boolean findJob = false;
		while (m.find(index)) {
			index = m.start() + 1;
			jobData2 = jobData;
			jobData = new JobData();
			jobString = cont.substring(index, cont.indexOf("XW.doJob", index));
			Pattern p2 = Pattern.compile("<div id=\"job_do_div_(\\d+?)\">");
			Matcher m2 = p2.matcher(jobString);
			if (!m2.find()) {
				jobData1 = null;
				return false;
			}
			String jobId = m2.group(1);
			jobData.id = jobId;
			jobData.city  = city;
			jobData.jpid = jpid;
			int beginIndex = cont.lastIndexOf("<b>", index) + 3;
			int endIndex = cont.indexOf("</b>", beginIndex);
			String jobName = cont.substring(beginIndex, endIndex).trim();
			jobData.name = jobName;
			p2 = Pattern.compile("<b>(\\d+?)</b> ?能量");
			m2 = p2.matcher(jobString);
			if (m2.find()) {
				jobData.energy = Integer.parseInt(m2.group(1));
			}
			if (!"100".equals(m.group(1))) {
				findJob = true;
				break;
			}
		}
		if (findJob) {
			p = Pattern.compile("c_jpid=\"(.+?)\" jobname=\"(.+?)\"");
			m = p.matcher(jobString);
			if (!m.find()) {
				if (jobBuy(jobString, jobData.jpid)) {
					jobData1 = jobData;
				} else {
					jobData1 = null;
				}
			} else {
				//dependent
				int jpid2 = Integer.parseInt(m.group(1));
				String jobName = m.group(2);
	
				if (jpid != jpid2) {
					cont = get(getJobURL(jpid2), JOB_URL);
				}
				
				index = cont.indexOf("<b>" + jobName + "</b>");
				int index2 = cont.indexOf("XW.doJob", index);
				int index3 = cont.indexOf(",", index2);
				String jobId = cont.substring(index2 + 9, index3);
				log("缺少道具，找到依赖任务：" + jobName + " (" + jobId  + ")");
				jobData = new JobData();
				jobData.id = jobId;
				jobData.name = jobName;
				jobData.energy = 10;
				jobData1 = jobData;
			}
			return true;
		} else {
			jobData2 = null;
		}
		return false;
	}
	
	private boolean jobBuy(String jobString, int jpid) throws IOException {
		Pattern p = Pattern.compile("need=\"(\\d+?)\" cash=\"(\\d+?)\" ikey=\"(.+?)\" name=\"(.+?)\"");
		Matcher m = p.matcher(jobString);
		int index = 0;
		while (m.find(index)) {
			index = m.start() + 1;
			int need = Integer.parseInt(m.group(1));
			String ikey = m.group(3);
			
			String url = HOST_URL + "/!ajax_buyinv.php?buyinv=" + ikey + "%253D" + need + "&c_jpid=" + jpid + "&where=&cid=" + cid + "&tmp=" + Math.random() + "&rt=json";
			String cont = get(url, JOB_URL);
			try {
				JSONObject jobj = new JSONObject(cont);
				if ("notice".equals(jobj.getString("flag"))) {
					return false;
				}
			} catch (JSONException e) {
				return false;
			}
		}
		return true;
	}
	
	private void fight() throws IOException {
		String cont = get(FIGHT_URL, null);
		Pattern p = Pattern.compile("\"teamnum\":\"?(\\d+?)\"?,");
		Matcher m = p.matcher(cont);
		if (!m.find()) {
			return;
		}
		int teamnum = Integer.parseInt(m.group(1));
		if (teamnum == 1) {
			String url = HOST_URL + "/!ajax_fight.php";
			String html = post(url, FIGHT_URL, new NameValuePair[]{
					new NameValuePair("l", "a"),
					new NameValuePair("fightname", "123"),
					new NameValuePair("cid", "" + cid),
					new NameValuePair("tmp", "" + Math.random())
			});
			p = Pattern.compile("\"uid\":(\\d+?),");
			m = p.matcher(html);
			StringBuffer uids = new StringBuffer();
			int index = 0;
			while (m.find()) {
				index ++;
				String uid = m.group(1);
				uids.append(uid);
				if (index < 4) {
					uids.append("-");
				} else {
					break;
				}
			}
			url = HOST_URL + "/!ajax_fightteam.php";
			post(url, FIGHT_URL, new NameValuePair[]{
					new NameValuePair("l", "a"),
					new NameValuePair("m", uids.toString()),
					new NameValuePair("cid", "" + cid),
					new NameValuePair("tmp", "" + Math.random())
			});
			log("组建战队123");
			teamnum = 5;
			cont = get(FIGHT_URL, null);
		}
		stamina = getUserProperty(cont, "stamina");
		health = getUserProperty(cont, "health");
		level = getLevel(cont);
		while (stamina > 0) {
			TreeMap<String, Team> treeMap = new TreeMap<String, Team>();
			String[] strs = cont.split("<tr id=\"");
			p = Pattern.compile(">([^><]+?)</a>.+?首领级别(\\d+?)级.+?<td class=\"tac\">(\\d+?)</td>.+?XW[.]fight[.]tofight[(]'([^']+?)'[)]", Pattern.DOTALL);
			for (int i = 0, n = strs.length; i < n; i++) {
				m = p.matcher(strs[i]);
				if (m.find()) {
					String teamName = m.group(1);
					int l = Integer.parseInt(m.group(2));
					int num = Integer.parseInt(m.group(3));
					String objid = m.group(4);
					if (l <= level && ((teamnum > 20 && num <= teamnum) || (teamnum < 20 && num == 5))) {
						Team t = new Team();
						t.level = level;
						t.num = num;
						t.name = teamName;
						t.objid = objid;
						treeMap.put(num + objid, t);
					}
				}
			}
			for (Iterator<Team> it = treeMap.values().iterator(); it.hasNext(); ) {
				boolean result = fight(it.next());
				if (result) {
					return;
				}
			}
			cont = get(FIGHT_URL, null);
			stamina = getUserProperty(cont, "stamina");
			health = getUserProperty(cont, "health");
		}
	}
	
	private boolean fight(Team t) throws IOException {
//		int code = 0;
		if (health < 70) {
			hospital();
		}
		if (stamina == 0) {
			return true;
		}
		String result = post(HOST_URL + "/!ajax_fight.php",
				FIGHT_URL, new NameValuePair[]{
				new NameValuePair("objid", t.objid), new NameValuePair("cid", "" + cid), 
				new NameValuePair("tmp", String.valueOf(Math.random()))});
		String msg = "挑战" + t.name + "，等级" + t.level + "，团队人数" + t.num;
		if (result.trim().equals("")) {
			log("\t请求失败，请稍后重试");
		} else if (result.trim().equals("e7")) {
			log("\t黑暗势力在你的强力威慑下仓皇逃跑，去找其它的对手吧");
//			code = 1;
		} else if (result.trim().equals("e6")) {
			log("\t对不起，不能频繁挑战该对手");
//			code = 2;
		} else if (result.startsWith("e13")) {
			err("\t战斗失败，请确认合法请求");
//			code = 1;
		} else if (result.trim().equals("e2")) {
			log("\t你的战斗值为0，无法战斗，请耐心等待战斗值回涨");
			return true;
		} else {
			stamina = getUserProperty(result, "stamina");
			health = getUserProperty(result, "health");
			if (result.indexOf("http://img.kaixin001.com.cn/i3/spiderman/bg_banner_win.gif") > -1) {
				log(msg + "\t战斗胜利，剩余生命值：" + health + "，战斗值：" + stamina);
			} else {
				err(msg + "\t战斗失败，剩余生命值：" + health + "，战斗值：" + stamina);
			}
		}
		return false;
	}
	
	private void hospital() throws IOException {
		if (cid != 2) {
			get(HOST_URL + "/hospital.php?cid=2&t=" + Math.random(), null);
		}
		String result = post(HOST_URL + "/!hospital.php", HOST_URL
				+ "/hospital.php", new NameValuePair[] {
				new NameValuePair("l", "a"), new NameValuePair("cid", "2"),
				new NameValuePair("tmp", String.valueOf(Math.random())) });
		health = getUserProperty(result, "health");
		log("恭喜你重获健康！");
		if (cid != 2) {
			get(HOST_URL + "/hospital.php?cid=" + cid + "&t=" + Math.random(), null);
		}
	}

	//
	public boolean exchange() throws IOException {
		String html = get(COLLECTION_URL, null);
		String flag = "show";
		String ccid = getCcid(html, flag);
		while (ccid != null) {
			html = exchange(ccid, flag);
			ccid = getCcid(html, flag);
		}
		
		flag = "exchange";
		ccid = getCcid(html, flag);
		while (ccid != null) {
			html = exchange(ccid, flag);
			ccid = getCcid(html, flag);
		}
			
		return true;
	}
	
	private String getCcid(String html, String flag) {
		String ccid = null;
		Pattern p = Pattern.compile("<a.+?href=\"javascript:XW[.]Col[.]exchange[(]'(\\d+?)','" + flag + "'[)];\"");
		Matcher m = p.matcher(html);
		if (m.find()) {
			ccid = m.group(1);
		}
		return ccid;
	}
	
	private String exchange(String ccid, String flag) throws IOException {
		String url = KXUtil.HOST_URL + "/!spiderman/!ajax_collection.php?flag=" + flag + "&ccid=" + ccid + "&cid=" + cid + "&tmp=" + Math.random() + "&rt=json";
		String result = get(url, COLLECTION_URL);
		try {
			JSONObject jobj = new JSONObject(result);
			if (jobj.has("wap")) {
				log(jobj.getString("wap"));
			} else if (jobj.has("error")) {
				err(jobj.getString("error"));
			}
		} catch (JSONException e) {
			e.printStackTrace();
		}
		url = KXUtil.HOST_URL + "/!spiderman/!inventory.php?item=collection&flag=list&cid=" + cid + "&tmp=" + Math.random();
		return get(url, COLLECTION_URL);
	}
	
	// ################### help ######################
	private void help() throws UnsupportedEncodingException, IOException {
		String url = KXUtil.HOST_URL + "/!spiderman/index.php";
		String html = get(url, null);
		
		donateEnergy(html);
		
		Pattern p = Pattern.compile("javascript[:]XW[.]Evt[.]helpNF[(](\\d+?)[)];");
		while (html != null) {
			Matcher m = p.matcher(html);
			if (m.find()) {
				String id = m.group(1);
				String helpnf = KXUtil.HOST_URL + "/!spiderman/!ajax_event.php?tuid=" + id + "&flag=helpnf&cid=" + cid + "&tmp=" + Math.random() + "&rt=json";
				String json = get(helpnf, url);
				try {
					JSONObject jobj = new JSONObject(json);
					if (jobj.has("flag") && "suc".equals(jobj.getString("flag"))) {
						log(jobj.getString("content"));
						String dohelpnf = KXUtil.HOST_URL + "/!spiderman/!ajax_event.php?tuid=" + id + "&flag=dohelpnf&cid=" + cid + "&tmp=" + Math.random();
						String cont = get(dohelpnf, url);
						if (cont.indexOf("XW.Evt.helpNFNull();") > -1) {
							return;
						}
					} else {
						err(json);
					}
				} catch (JSONException e) {
					err(json);
					e.printStackTrace();
				}
			} else {
				return;
			}
			String listurl =  KXUtil.XW_URL + "/!ajax_friend.php?flag=list&cid=" + cid + "&tmp=" + Math.random();
			html = get(listurl, url);
		}
	}
	
	private static Set<String> donateUids = new HashSet<String>();
	
	private void donateEnergy(String cont) throws IOException {
		//赠送好友爱心能量包
		Pattern p = Pattern.compile("XW[.]Inv[.]donateEnergy[(](\\d+?)[)]");
		Matcher m = p.matcher(cont);
		Set<String> idSet = new HashSet<String>();
		int index = 0;
		while (m.find(index)) {
			index = m.start() + 1;
			idSet.add(m.group(1));
		}
		for (String uid : idSet) {
			if (donateUids.contains(uid)) {
				continue;
			}
			String url = KXUtil.XW_URL + "/!ajax_donate_energy.php?uid=" + uid + "&rt=json&cid=" + cid + "&tmp=" + Math.random();
			cont = get(url, HOST_URL);
			try {
				JSONObject jobj = new JSONObject(cont);
				log(KXUtil.findMessage(jobj.getString("html")));
				donateUids.add(uid);
			} catch (JSONException e) {
				err(cont, e);
			}
		}
	}
	
	// ################################
	private void secretbag() throws IOException {
		String url = KXUtil.HOST_URL + "/!spiderman/inventory.php?item=loot";
		String cont = get(url, null);
		while (cont != null) {
			if (cont.indexOf("XW.Inv.magic('Secretbag_Inv');") == -1) {
				return;
			}
			Pattern p = Pattern.compile("id=\"num_Secretbag_Inv\">(\\d+?)</b>");
			Matcher m = p.matcher(cont);
			cont = null;
			if (m.find()) {
				int num = Integer.parseInt(m.group(1));
				if (num < 1) {
					return;
				}
				String showurl = KXUtil.HOST_URL + "/!spiderman/!ajax_inv.php?ikey=Secretbag_Inv&flag=show_magic&cid=" + cid + "&tmp=" + Math.random();
				waitAMoment();
				String html = get(showurl, url);
				p = Pattern.compile("选择锤子：今天还可砸(\\d+?)次黄金神秘蛋");
				m = p.matcher(html);
				if (m.find()) {
					int num2 = Integer.parseInt(m.group(1));
					if (num2 < 1) {
						return;
					}
					p = Pattern.compile("七彩水晶锤</div><div class=\"l c_red\"><span>可开：(\\d+?)次");
					m = p.matcher(html);
					if (m.find()) {
						int num3 = Integer.parseInt(m.group(1));
						if (num3 < 1) {
							return;
						}
						String magicurl = KXUtil.HOST_URL + "/!spiderman/!ajax_inv.php?ikey=Secretbag_Inv&flag=magic&blockkey=Qicaikey_Inv&cid=" + cid + "&tmp=" + Math.random() + "&rt=json";
						waitAMoment();
						html = get(magicurl, url);
						try {
							JSONObject jobj = new JSONObject(html);
							if (jobj.getString("flag").equals("suc")) {
								log(KXUtil.findMessage(jobj.getString("title")));
							} else {
								err(html);
							}
						} catch (JSONException e) {
							e.printStackTrace();
						}
						String listurl = KXUtil.HOST_URL + "/!spiderman/!inventory.php?item=loot&flag=list&cid=" + cid + "&tmp=" + Math.random();
						cont = get(listurl, url);
					}
				} else {
					return;
				}
			}
		}
	}
	
	private void dianchi() throws IOException {
		String url = KXUtil.XW_URL + "/inventory.php?item=loot";
		String html = get(url, null);
		if (html.indexOf("javascript:XW.Inv.showConsume('Dianchi_Inv')") > -1) {
			String useurl = KXUtil.XW_URL + "/!ajax_inv.php?ikey=Dianchi_Inv&flag=consume&orderid=tr_&cid=" + cid + "&tmp=" + Math.random();
			html = get(useurl, url);
			if (html.indexOf("你成功使用了") > -1) {
				log("你成功使用了超能电池，能量值+200点");
			} else {
				log("\u4eca\u5929\u4f60\u4f7f\u7528\u7684\u6b21\u6570\u5df2\u7ecf\u8fbe\u5230\u4e0a\u9650\u4e86");
			}
		}
	}
	
	private void buyInv(String buyinv, String num) throws IOException {
		String url = KXUtil.XW_URL + "/!ajax_buyinv.php?buyinv=" + buyinv + "%253D" + num + "&c_jpid=0&where=&cid=2&tmp=" + Math.random() +"&rt=json";
		String json = get(url, null);
		try {
			JSONObject jobj = new JSONObject(json);
			if (jobj.getString("flag").equals("suc")) {
				log(jobj.getString("wap"));
			}
		} catch (JSONException e) {
			e.printStackTrace();
			err(json);
		}
	}
	private void mangu() throws IOException {
		String url = KXUtil.XW_URL + "/forecast_sea.php";
		String html = get(url, null);
		energy = getEnergy(html);
		
		if (html.indexOf("/!spiderman/city_transform.php?ckey=Bangkok") > -1) {
			String transform = KXUtil.XW_URL + "/city_transform.php?ckey=Bangkok";
			get(transform, url);
			log("进军曼谷！");
			return;
		}
		
		if (html.indexOf("购买宝石") > -1) {
			Pattern p = Pattern.compile("id=\"user_cash\">\\$(\\d+?)</b>");
			Matcher m = p.matcher(html);
			if (m.find()) {
				long cash = Long.parseLong(m.group(1));
				if (cash >= 1000000000) {
					String buyurl = KXUtil.XW_URL + "/!ajax_forecast_buyinv.php?buyinv=Yixiangbaoshi_Inv%253D1&where=&cid=2&tmp=" + Math.random() + "&rt=json";
					String cont = get(buyurl, url);
					if (cont.indexOf("\"flag\":\"suc\"") > -1) {
						log("购买宝石");
					} else {
						err(cont);
					}
				}
			}
		}
		
		if (html.indexOf("挑战狂人托尼") > -1) {
			String joburl = KXUtil.XW_URL + "/job.php?c_jpid=10";
			String cont = get(joburl, url);
			String[] buyinvs = new String[]{"Diangun_Inv", "Huajia_Inv", "Sedan_Inv"};
			for (int i = 0, n = buyinvs.length; i < n; i++) {
				Pattern p = Pattern.compile("need=\"(\\d+?)\" cash=\"(\\d+?)\" ikey=\"" + buyinvs[i] + "\"");
				Matcher m = p.matcher(cont);
				if (m.find()) {
					buyInv(buyinvs[i], m.group(1));
				}
			}
			if (cont.indexOf("PK狂人托尼") > -1) {
				energy = getEnergy(cont);
				Pattern p = Pattern.compile("能量\\：</span><b class=\"cf\">(\\d+?)</b>");
				Matcher m = p.matcher(cont);
				if (m.find()) {
					int e = Integer.parseInt(m.group(1));
					if (energy >= e) {
						health = getUserProperty(cont, "health");
						if (health != 100) {
							hospital();
						}
						String bossfight = KXUtil.XW_URL + "/!ajax_bossfight.php?c_bossid=9&flag=boss&cid=2&tmp=" + Math.random();
						cont = get(bossfight, joburl);
						int num = 0;
						p = Pattern.compile("<div id=\"Nlkuai_Inv_num\"[^>]+?>×(\\d+?)</div>");
						m = p.matcher(cont);
						if (m.find()) {
							num = Integer.parseInt(m.group(1));
						}
						
						String attack = KXUtil.XW_URL + "/!ajax_bossfight.php?c_bossid=9&flag=boss_attack&cid=2&tmp=" + Math.random();
						String useinv = KXUtil.XW_URL + "/!ajax_bossfight.php?ikey=Nlkuai_Inv&flag=useinv&c_bossid=9&cid=2&tmp=" + Math.random();
						while (health != 0) {
							waitAMoment();
							cont = get(attack, bossfight);
							if (cont.indexOf("恭喜你，") > -1) {
								break;
							}
							if (num > 0) {
								cont = get(useinv, bossfight);
								num--;
							}
							health = getUserProperty(cont, "health");
						}
						if (health == 0) {
							err("挑战失败");
						} else {
							log("恭喜你，打败狂人托尼!");
						}
					} else {
						log("能量不足（当前：" + energy + "，需要：" + e + "），无法挑战！");
					}
				}
			}
		}
		
		Pattern p = Pattern.compile("需收割10次橡胶，每次消耗100能量，获120经验。<br /><span id=\"jobprogress\">完成(\\d+?)\\%");
		Matcher m = p.matcher(html);
		if (m.find()) {
			int jobprogress = Integer.parseInt(m.group(1));
			if (jobprogress != 100) {
				String joburl = KXUtil.XW_URL + "/!ajax_dojob.php?c_jid=174&flag=forecast&cid=2&tmp=" + Math.random() + "&rt=json";
				energy = getEnergy(html);
				while (energy >= 100) {
					String json = get(joburl, url);
					try {
						JSONObject jobj = new JSONObject(json);
						jobprogress = jobj.getInt("jobprogress");
						log("收割橡胶，进度" + jobprogress + "%");
						if (jobprogress == 100) {
							break;
						}
						energy = getEnergy(jobj.getString("profilejs"));
					} catch (JSONException e) {
						e.printStackTrace();
						err(json);
						break;
					}
				}
			}
		}
//		<td id="heff"><a href="/!spiderman/job.php?c_jpid=10" class="butt_operate">挑战狂人托尼</a></td>
//		<td id="gem"><a href="javascript:XW.forecast.buyInv('Yixiangbaoshi_Inv');" class="butt_operate" id="baoshi">购买宝石</a></td>
//		<td id="rubber"><a href="javascript:XW.forecast.doFcJob(174);" class="butt_operate" id="shouge">收割橡胶</a></td>
//		<td id="passport"><a href="/!spiderman/job.php?c_jpid=10" class="butt_operate">继续做任务</a></td>
	}
	
	private void propterty() throws IOException {
		int c = cid;
		for (int i = 0, n = cids.size(); i < n; i++) {
			c = cids.get(i);
			waitAMoment();
			propterty(c);
		}
		if (c != cid) {
			changeCity(cid);
		}
	}
	
	private void propterty(int cid) throws IOException {
		String propertyurl = KXUtil.XW_URL + "/property.php?cid=" + cid + "&t=" + Math.random();
		String html = get(propertyurl, INDEX_URL);
		if (html.indexOf("window.location = '/!spiderman/forecast_") > -1) {
			return;
		}
		String url = KXUtil.XW_URL + "/!api_property_show.php?r="
				+ Math.random();
		String xml = get(url, propertyurl);
		boolean canRent = false;
		Map<String, Long> buyMap = new LinkedHashMap<String, Long>();
		Map<String, Long> updateMap = new LinkedHashMap<String, Long>();
		try {
			DocumentBuilder builder = DocumentBuilderFactory.newInstance()
					.newDocumentBuilder();
			InputStream is = new ByteArrayInputStream(xml.getBytes("UTF-8"));
			Document doc = builder.parse(is);
			level = Integer.parseInt(doc.getElementsByTagName("melevel")
					.item(0).getTextContent());
			cash = Long.parseLong(doc.getElementsByTagName("cash").item(0)
					.getTextContent());
			NodeList nodeList = doc.getElementsByTagName("property").item(0).getChildNodes();
			for (int i = 0, n = nodeList.getLength(); i < n; i++) {
				Node node = nodeList.item(i);
				if ("item".equals(node.getNodeName())) {
					NodeList subNodeList = node.getChildNodes();
					Map<String, String> attributes = new HashMap<String, String>();
					for (int j = 0, m = subNodeList.getLength(); j < m; j++) {
						Node subNode = subNodeList.item(j);
						String nodeName = subNode.getNodeName();
						String nodeValue = subNode.getTextContent();
						attributes.put(nodeName, nodeValue);
					}
					if (attributes.containsKey("lefttime")) {
						int lefttime = Integer.parseInt(attributes.get("lefttime"));
						if (lefttime <= 0) {
							canRent = true;
						}
					}
					if (!attributes.containsKey("newgrade")) {
						int l = Integer.parseInt(attributes.get("level"));
						if (level >= l) {
							long price = Long.parseLong(attributes.get("price"));
							if (cash >= price) {
								buyMap.put(attributes.get("pkey"), price);
							}
						}
					}  else {
						int newgrade = Integer.parseInt(attributes.get("newgrade"));
						int maxgrade = Integer.parseInt(attributes.get("maxgrade"));
						if (newgrade < maxgrade) {
							long upgradefee = Long.parseLong(attributes.get("upgradefee"));
							if (cash >= upgradefee) {
								updateMap.put(attributes.get("pkey"), upgradefee);
							}
						}
					}
				}
			}
		} catch (Exception e) {
			err(xml, e);
		}
		if (canRent) {
			url += "&l=a";
			xml = get(url, propertyurl);
			try {
				DocumentBuilder builder = DocumentBuilderFactory.newInstance()
						.newDocumentBuilder();
				InputStream is = new ByteArrayInputStream(xml.getBytes("UTF-8"));
				Document doc = builder.parse(is);
				cash = Long.parseLong(doc.getElementsByTagName("cash").item(0).getTextContent());
				for (int i = 0, n = doc.getElementsByTagName("msg").getLength(); i < n; i++) {
					String msg = doc.getElementsByTagName("msg").item(i).getTextContent();
					if (msg != null && msg.trim().length() > 0) {
						log(KXUtil.findMessage(msg));
					}
				}
			} catch (Exception e) {
				err(xml, e);
			}
		}
		for (Iterator<String> it = buyMap.keySet().iterator(); it.hasNext(); ) {
			String pkey = it.next();
			long price = buyMap.get(pkey);
			if (cash >= price) {
				xml = get(KXUtil.XW_URL + "/!api_property.php?l=c&pkey=" + pkey + "&rd="
							+ Math.random(), null);
				try {
					DocumentBuilder builder = DocumentBuilderFactory.newInstance()
							.newDocumentBuilder();
					InputStream is = new ByteArrayInputStream(xml.getBytes("UTF-8"));
					Document doc = builder.parse(is);
					cash = Long.parseLong(doc.getElementsByTagName("cash").item(0).getTextContent());
					String msg = doc.getElementsByTagName("msg").item(0).getTextContent();
					if (msg != null && msg.trim().length() > 0) {
						log(KXUtil.findMessage(msg));
					}
				} catch (Exception e) {
					err("", e);
				}
			}
		}
		
		String pkey = "Baoshifang_Pro";
		if (updateMap.containsKey(pkey)) {
			long upgradefee = updateMap.get(pkey);
			while(true) {
				if (cash >= upgradefee) {
					xml = get(KXUtil.XW_URL + "/!api_property.php?l=a&pkey=" + pkey + "&rd="
							+ Math.random(), null);
					upgradefee =Long.MAX_VALUE;
					try {
						DocumentBuilder builder = DocumentBuilderFactory.newInstance()
								.newDocumentBuilder();
						InputStream is = new ByteArrayInputStream(xml.getBytes("UTF-8"));
						Document doc = builder.parse(is);
						cash = Long.parseLong(doc.getElementsByTagName("cash").item(0).getTextContent());
						String msg = doc.getElementsByTagName("msg").item(0).getTextContent();
						if (msg != null && msg.trim().length() > 0) {
							String name = doc.getElementsByTagName("name").item(0).getTextContent();
							log(name + KXUtil.findMessage(msg));
						}
						int newgrade = Integer.parseInt(doc.getElementsByTagName("newgrade").item(0).getTextContent());
						int maxgrade = Integer.parseInt(doc.getElementsByTagName("maxgrade").item(0).getTextContent());
						if (newgrade < maxgrade) {
							upgradefee = Integer.parseInt(doc.getElementsByTagName("upgradefee").item(0).getTextContent());
						}
					} catch (Exception e) {
						err("", e);
					} 
				} else {
					break;
				}
			}
		}
	}
	
	private void gift() throws IOException {
		String url = KXUtil.HOST_URL + "/friend/editorder.php";
		String html = get(url, null);
		Pattern p = Pattern.compile("\"uid\":\"(\\d+?)\",");
		Matcher m = p.matcher(html);
		while (m.find()) {
			String uid = m.group(1);
//			if (uid.equals(KXUtil.getMainUserUid())) {
//				continue;
//			}
			boolean finished = giftFree(uid, "Nlkuai_Inv", "");
			if (finished) {
				return;
			}
			waitAMoment();
		}
	}

	private boolean giftFree(String uid, String wkey, String msg) throws IOException {
		String url = KXUtil.XW_URL + "/!ajax_gift.php?wkey=" + wkey + "&type=loot&msg=" + msg + "&uid=" + uid + "&flag=freegift&cid=" + cid + "&tmp=" + Math.random() + "&rt=json";
		String html = gift(url, uid);
		if (html.indexOf("\\u4f60\\u4eca\\u5929\\u9001\\u514d\\u8d39\\u793c\\u7269\\u8fbe\\u5230\\u4e86\\u6700\\u5927\\u9650\\u989d") > -1) {
			return true;
		}
		return false;
	}
	
	private String gift(String url, String uid) throws IOException {
		String html = get(url, null);
		try {
			JSONObject jobj = new JSONObject(html);
			if ("suc".equals(jobj.getString("flag"))) {
				log(KXUtil.findMessage(jobj.getString("html")));
			} else if ("notice".equals(jobj.getString("flag"))) {
				log(KXUtil.findMessage(jobj.getString("info")));
			} else if ("err".equals(jobj.getString("flag"))) {
				err(KXUtil.findMessage(jobj.getString("error")));
			}
		} catch (JSONException e) {
			err(html);
			e.printStackTrace();
		}
		return html;
	}
	
	public void consume() throws Exception {
		String url = KXUtil.XW_URL + "/inventory.php?item=loot";
		String cont = get(url, null);
		if (cont.indexOf("XW.Inv.consume('Zsnlb_Inv','tr_')") > -1) {
			if (energy > 40) {
				err("请把能量用完再使用能量包。");
				return;
			}
			int threshold = 100;
			Pattern p = Pattern.compile("<span id='user_experience'>(\\d+?)</span>/<span id='next_level_experience'>(\\d+?)</span>"); 
			Matcher m = p.matcher(cont);
			if (m.find()) {
				int user_experience = Integer.parseInt(m.group(1));
				int next_level_experience = Integer.parseInt(m.group(2));
				if (next_level_experience - user_experience  < threshold) {
					err("还差" + (next_level_experience - user_experience) + "就升级了，请待会儿再使用能量包。");
					return;
				}
			}
			String ajaxUrl = KXUtil.XW_URL + "/!ajax_inv.php?ikey=Zsnlb_Inv&flag=consume&orderid=tr_&cid=" + cid + "&tmp=" + Math.random();
			cont = get(ajaxUrl, url);
			log("爱心能量包已使用，能量值已加满，23小时后可以再次接收朋友的爱心能量包。");
		} else if (cont.indexOf("可以接收新的能量包") > -1) {
			err("请接收新的能量包。");
		} else {
			Pattern p = Pattern.compile("XW[.]leftTimer[(](\\d+?),.+?XW[.]Inv[.]consumeCanReDonate[(][)]"); 
			Matcher m = p.matcher(cont);
			if (m.find()) {
				int sec = Integer.parseInt(m.group(1));
				int hour = sec / 3600;
				int min = sec % 3600 /60;
				log("距离下次可接收的时间：" + hour + "小时" + min + "分");
			}
		}
			
	}
	
	public void gaming() throws Exception {
		String url = HOST_URL + "/gaming.php?cid=" + cid + "&t=" + Math.random();
		String html = get(url, null);
		Pattern p = Pattern.compile(">(\\d+?)</span> 次投注机会");
		Matcher m = p.matcher(html);
		if (m.find()) {
			int i = Integer.parseInt(m.group(1));
			if (i > 0) {
				Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT+8"));
				int day = c.get(Calendar.DAY_OF_WEEK);
				Set<Integer> s = new HashSet<Integer>();
				Random r = new Random();
				while (s.size() < 4) {
					int num = r.nextInt(63);
					if (!s.contains(num + 8)) {
						s.add(num + 8);
					}
				}
				StringBuffer sb = new StringBuffer();
				sb.append(day);
				for (int num : s) {
					sb.append("-");
					sb.append(num);
				}
				String result = post(HOST_URL + "/!ajax_ticket.php", url, 
					new NameValuePair[] {
						new NameValuePair("l", "a"),
						new NameValuePair("t", sb.toString()),
						new NameValuePair("cid", String.valueOf(cid)),
						new NameValuePair("tmp", String.valueOf(Math.random())) 
				});
				String[] results = result.split("\\|");
				log("投注成功，你投注的号码是" + sb.toString() + "。" + KXUtil.findMessage(results[results.length - 1]));
			}
		}
	}
	
	private void log(String msg) {
		System.out.println("Thread[" + index + "] " + email + " " + msg);
	}
	
	private void err(String msg) {
		System.err.println("Thread[" + index + "] " + email + " " + msg);
	}
	
	private void err(String msg, Exception e) {
		System.err.println("Thread[" + index + "] " + email + " " + msg);
		e.printStackTrace();
	}
	
	public class JobData{
		public String id;
		public int jpid;
		public int city;
		public String name;
		public int energy;
	}
	
	public static class Team {
		public String objid;
		public int level;
		public int num;
		public String name;
	}

}

